package com.djsblog.util;

import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Paths;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import com.djsblog.entity.Blog;
import com.djsblog.entity.PageBean;
import com.djsblog.enums.DateStyle;
import com.jfinal.kit.PathKit;
//import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;


/**
 * lunce索引工具
 * @author 但劲松
 *
 */
public class LunceUtil {
	private Directory directory;
	/**
	 * 获取索引写者方法
	 * @param url
	 * @return
	 */
	private IndexWriter getIndexWriter(String url){
		IndexWriter writer = null;
		try {
			directory = FSDirectory.open(Paths.get(url));
			Analyzer analyzer = new SmartChineseAnalyzer();		//智能中文分词
			IndexWriterConfig conf = new IndexWriterConfig(analyzer );
			writer = new IndexWriter(directory, conf);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return writer;
	}
	/**
	 * 创建索引
	 * @param blog
	 */
	public void creatIndex(Blog blog){
		IndexWriter writer = getIndexWriter(PathKit.getWebRootPath()+"/src/main/webapp/LUNCE");//索引目录
		Document doc = new Document();				
		doc.add(new StringField("id",String.valueOf(blog.getId()), Store.YES));				//索引项目ID
		doc.add(new TextField("title", blog.getTitle(), Store.YES));			//索引标题
		doc.add(new StringField("created", DateUtil.DateToString(new Date(),DateStyle.YYYY_MM_DD_HH_MM_SS_EN), Store.YES));//索引日期
		doc.add(new TextField("summary", blog.getSummary(), Store.YES));		//索引概要
		try {
			writer.addDocument(doc);
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 更新索引
	 * @param blog
	 * @throws Exception
	 */
	public void updateIndex(Blog blog){
		IndexWriter writer = null;
		try {
		writer=getIndexWriter(PathKit.getWebRootPath()+"/src/main/webapp/LUNCE");//索引目录
		Document doc=new Document();
		doc.add(new StringField("id",String.valueOf(blog.getId()),Store.YES));
		doc.add(new TextField("title",blog.getTitle(),Store.YES));
		doc.add(new StringField("created",DateUtil.DateToString(new Date(), DateStyle.YYYY_MM_DD_HH_MM_SS_EN),Store.YES));
		doc.add(new TextField("summary",blog.getSummary(),Store.YES));
		writer.updateDocument(new Term("id",String.valueOf(blog.getId())), doc);
		writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	/**
	 * 删除索引
	 * @param blogId
	 * @throws Exception
	 */
	public void deleteIndex(String blogId){
		IndexWriter writer=getIndexWriter(PathKit.getWebRootPath()+"/src/main/webapp/LUNCE");//索引目录
		try {
		writer.deleteDocuments(new Term("id",blogId));
		writer.forceMergeDeletes(); 
		writer.commit();
		writer.close();
		}
		catch(Exception exception){
			exception.printStackTrace();
		}
	}
	/**
	 * 获取查询的集合
	 * @param q
	 * @return
	 */
	public List<Record> queryBlog(String q,PageBean pageBean){
		List<Record> blogList=null;
		try {
		directory=FSDirectory.open(Paths.get(PathKit.getWebRootPath()+"/src/main/webapp/LUNCE"));
		IndexReader reader=DirectoryReader.open(directory);
		IndexSearcher is=new IndexSearcher(reader);
		SmartChineseAnalyzer analyzer=new SmartChineseAnalyzer();
		
		//构建混合查询约束
		BooleanQuery.Builder booleanQuery=new BooleanQuery.Builder();
		
		QueryParser parser=new QueryParser("title", analyzer);
		QueryParser parser2=new QueryParser("summary", analyzer);
		Query queryTitle=parser.parse(q);
		Query queryText=parser2.parse(q);

		booleanQuery.add(queryTitle, Occur.SHOULD);
		booleanQuery.add(queryText, Occur.SHOULD);
		//查询前100条
		TopDocs hits=is.search(booleanQuery.build(), 200);
		
		//构建高亮分数
		SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font style='color:red;'><u><strong>", "</strong></u></font>");
		//设置高亮到查询约束
		QueryScorer scorer=new QueryScorer(queryText);
		//构建分数代码
		Highlighter highlighter=new Highlighter(simpleHTMLFormatter, scorer);
		blogList=new LinkedList<Record>();
		for(int i=pageBean.getStart();i<pageBean.getStart()+5;i++){
		//	System.out.println(i);
			ScoreDoc scoreDoc = null;
			if(i <= hits.scoreDocs.length-1)
				scoreDoc = hits.scoreDocs[i];
			else
				break;
			if(scoreDoc != null){
				Document doc=is.doc(scoreDoc.doc);
				Record blog=new Record();
				getHighterCode(highlighter, blog, doc, analyzer);
				blogList.add(blog);
			}
		}
		return blogList;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return blogList;
	}
	/**
	 * 索引查询  获取对应博客的高亮代码
	 * @param highlighter	
	 * @param blog			
	 * @param doc			
	 * @param blog			
	 */
	public void getHighterCode(Highlighter highlighter,Record blog,Document doc,SmartChineseAnalyzer analyzer){
		try{
			blog.set("id", Long.parseLong(doc.get("id")));
//			blog = Db.findById("blog",Long.parseLong(doc.get("id")));
			blog.set("created", DateUtil.StringToDate(doc.get("created")));
			String title=doc.get("title");
			String text=doc.get("summary");
			if(title!=null){
				TokenStream tokenStream=analyzer.tokenStream("title", new StringReader(title));
				String hTitle=highlighter.getBestFragment(tokenStream, title);
				if(StringUtil.isEmpty(hTitle)){
					blog.set("title", title);
				}else{
					blog.set("title", hTitle);
				}
			}
			if(text!=null){
				TokenStream tokenStream=analyzer.tokenStream("summary", new StringReader(text));
				String hText=highlighter.getBestFragment(tokenStream, text);
				if(StringUtil.isEmpty(hText)){
					if(text.length()<=200){
						blog.set("text", text);
					}else{
						blog.set("text", text.substring(0, 200));
					}
				}else{
					blog.set("text", hText);
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}
